package com.hsh.disruptor;

import com.google.common.util.concurrent.RateLimiter;
import com.lmax.disruptor.*;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;
import com.lmax.disruptor.util.DaemonThreadFactory;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class LongEventMain {
    public static void main(String[] args) throws Exception {
        // The factory for the event1
        LongEventFactory factory = new LongEventFactory();

        // Specify the size of the ring buffer, must be power of 2.
        int bufferSize = 1<<4;

        // Construct the Disruptor
        final Disruptor<LongEvent> disruptor = new Disruptor<>(LongEvent::new, bufferSize, DaemonThreadFactory.INSTANCE,
                ProducerType.SINGLE, new TimeoutBlockingWaitStrategy(3, TimeUnit.SECONDS));

        //new TimeoutBlockingWaitStrategy(2, TimeUnit.SECONDS)

        disruptor.handleEventsWith(new LongEventHandler());
        // Connect the
        /*disruptor.setDefaultExceptionHandler(new ExceptionHandler<LongEvent>() {
            @Override
            public void handleEventException(Throwable ex, long sequence, LongEvent event) {
                System.out.println(ex);
            }

            @Override
            public void handleOnStartException(Throwable ex) {

            }


            @Override
            public void handleOnShutdownException(Throwable ex) {

            }
        });*/
        /*disruptor.handleEventsWithWorkerPool(new WorkHandler<LongEvent>() {
            @Override
            public void onEvent(LongEvent event) throws Exception {
                System.out.println(event.getValue());
            }
        });*/
//        disruptor.handleExceptionsFor(new EventHandler<LongEvent>() {
//            @Override
//            public void onEvent(LongEvent event, long sequence, boolean endOfBatch) throws Exception {
//
//            }
//        });

        // Start the Disruptor, starts all threads running
        final RingBuffer<LongEvent> queue = disruptor.start();

        final RateLimiter rateLimiter = RateLimiter.create(500);
        final ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {

            executorService.execute(() -> {
                final ByteBuf buf = PooledByteBufAllocator.DEFAULT.buffer(8);
                for (long l = 0; true; l++) {
                    //limite rate
                    rateLimiter.acquire();
                    buf.clear();
                    buf.writeLong(l);
                    //queue.publishEvent((event, sequence, buffer) -> event.set(buffer.getLong(0)), buf);
                    final boolean succ = queue.tryPublishEvent((event, Sequence, buffer) -> event.set(buffer.getLong(0)), buf);
                    if (!succ) {
                        System.out.println("queue is full ");
                    }
                }
            });
        }
    }
}